
/**************************************************************************
 * @doc pfr
 * @module pfr.C
 * Source for the power failure recovery module.
 *
 * Product     :   SoftPay 2000 (Global Payment Methodology).
 * <nl>Developer   :   Bruce Girdlestone
 * <nl>Notes       :
 *
 * @head3 PFR Functions |
 * @index | PFR
 * @end
 *
 * Copyright (c) 1996-2000 by VeriFone Inc. All rights reserved.
 *
 * No part of this software may be used, stored, compiled, reproduced,
 * modified, transcribed, translated, transmitted, or transferred, in any form
 * or by any means whether electronic, mechanical, magnetic, optical,
 * or otherwise, without the express prior written permission of VeriFone, Inc.
 *
 * Revision History
 * ------------------------------------------------------------------------
 $Log: \softpay\SPK2SIM\SOURCE\POWRFAIL\PFR.c $
 * ------------------------------------------------------------------------
 ********************************************************************************/


#define PFR_BUILD


#include <stdio.h>
#include <string.h>
#include <svc.h>
#include <stdlib.h>
#include <stdarg.h>
#include <acldev.h>
#include <aclconio.h>
#include <VarRec.h>

#include <project.h>
/** /#define DEBUG_PFR*/
#ifdef DEBUG_PFR
 #define DEBUG_95
#endif

#include <define.h>
#include <table.h>
#include <transact.h>
#include <funcs.h>
#include <transact.h>
#include <hdt.h>
#include <bdt.h>
#include <prtfuncs.h>
#include <form.h>
#include <print.h>
#include <mht.h>
#include <mit.h>
#include <logo.h>
#include <codesec.h>
#include <cdt.h>
#include <tblutil.h>
#include <pfr.h>
#include <settle.h>
#include <confio.h>
#include <operate.h>
#include <pbatch.h>
#include <ui.h>
#include <mem.h>
#include <msg.h>
#include <spdebug.h>
#include <logsys.h>
#include <init.h>

unsigned char pchPFRRecord[MAX_POWER_REC_FLEXI_SIZE];
unsigned char pchPFRExtDataFlexiRecord[MAX_POWER_REC_FLEXI_SIZE];
unsigned char pchRecoveryLinesFlexi[MAX_LINE_FLEXI_SIZE];
//char pchFormatMessageBuf[200];

unsigned short uinCurrentState;					// JPP
long PFR_LAST_TICKS = 0;
//char APPNAMES[20];
//unsigned int LOG_TYPES = LOGSYS_NONE;

/* This global variable is set if we are recovering */
int PFR_RECOVERING = 0;
static char PFR_DATE[PFR_DATE_SIZE];
static char PFR_TIME[PFR_TIME_SIZE];
int PFR_LAST_STATE;



/*****************************************************************************
* @func int | inAddExternalPfrData |
* @rdesc return values.
* @flag int    |  Error value. Non-Zero indicates an error has occured.
* @end
*****************************************************************************/
int inAddExternalPfrData(unsigned int uiFieldId,unsigned char * pchFieldData,int inDataSize)
{
	short error = 0;
	/* Add an un-typed field to a variable record */
	error = shVarAddField(pchPFRExtDataFlexiRecord,uiFieldId,pchFieldData,inDataSize);
	return (error);

}



/*****************************************************************************
* @func int | inGetExternalPfrData |
* Can be called to retrieve data stored before a power failure.
* @rdesc return values.
* @flag int    |  Error value. Non-Zero indicates an error has occured.
* @end
*****************************************************************************/
int inGetExternalPfrData(unsigned int uiFieldId,unsigned char * pchFieldData,int inDataSize)
{
	short inError = 0;
	 //jrd one source
    #ifdef __arm
    unsigned short inDataLen = 0;
    #endif
    #ifdef _TARG_68000
    unsigned int inDataLen = 0;
    #endif


	inError = shVarGetField(pchPFRExtDataFlexiRecord,
							uiFieldId,
							(unsigned char *)pchFieldData,
							inDataSize,
							&inDataLen);
	return (inError);
}//int



/*****************************************************************************
* @func int | inInitPowerFailFile |
* @rdesc return values.
* @flag int    |  Error value. Non-Zero indicates an error has occured.
* @end
*****************************************************************************/
int inInitPowerFailFile()
{
	int inError = 0;
	char inDummyData = 0;
	int inFileHandle = 0;
	int inBytesRead = 0;
	long offset = 0;
	int inCounterDummyData = 0;
//	short  inCurrentState=1;

	//pdebug (("inInitPowerFailFile"));

	/* Attempt to open the file */
	inFileHandle = open(POWER_FAIL_FILE_NAME,O_RDWR | O_CREAT);
	if (inFileHandle != -1)
	{
		/* Fill the file with NULLs */
		inBytesRead
		= write(inFileHandle,(char *)pchPFRRecord,MAX_POWER_REC_FLEXI_SIZE);
		close(inFileHandle);
	}//if

	inFileHandle = open(POWER_ADDITIONAL_PFR_FILE_NAME,O_RDWR | O_CREAT);
	if (inFileHandle != -1)
	{
		/* Fill the file with NULLs */
		inBytesRead
		= write(inFileHandle,(char *)pchPFRExtDataFlexiRecord,MAX_POWER_REC_FLEXI_SIZE);
		close(inFileHandle);
	}//if

	/* First, create a flexi-record containing the default power fail information */
	vVarInitRecord(pchPFRRecord, MAX_POWER_REC_FLEXI_SIZE, 0);
	vVarInitRecord(pchPFRExtDataFlexiRecord, MAX_POWER_REC_FLEXI_SIZE, 0);


	/* Add in the default fields */
	inError = shVarAddField(pchPFRRecord,
							PFR_STATE,
							(unsigned char *)&inDummyData,
	#ifdef _TARG_68000							
							sizeof(inDummyData)
	#endif
	#ifdef  __arm
							sizeof(int)
	#endif 
							);
	PFR_HANDLE_ERROR(inError);

	inError = shVarAddField(pchPFRRecord,
							PFR_UPDATE_TIME,
							(unsigned char *)&inDummyData,
#ifdef _TARG_68000		
							sizeof(inDummyData)
#endif 
#ifdef __arm
							sizeof(int)
#endif 
							);
	PFR_HANDLE_ERROR(inError);

	inError = shVarAddField(pchPFRRecord,
							PFR_UPDATE_DATE,
							(unsigned char *)&inDummyData,
#ifdef _TARG_68000									
							sizeof(inDummyData)
#endif 
#ifdef __arm
							sizeof(int)
#endif 
							);
	PFR_HANDLE_ERROR(inError);


	inError = shVarAddField(pchPFRRecord,
							PFR_FAILURE_COUNTER,
							(unsigned char *)&inCounterDummyData,
								
#ifdef _TARG_68000									

							sizeof(inCounterDummyData)
#endif 
#ifdef __arm
							sizeof(int)
#endif 
                            );
                            
	PFR_HANDLE_ERROR(inError);


	inError = shVarAddField(pchPFRRecord,
							PFR_REC_FAIL_COUNT,
							(unsigned char *)&inCounterDummyData,
#ifdef _TARG_68000		
							sizeof(inCounterDummyData)
#endif 
#ifdef __arm

							sizeof(int)
#endif 
							);
	PFR_HANDLE_ERROR(inError);


	inError = shVarAddField(pchPFRRecord,
							PFR_TRANOBJ_STORED,
							(unsigned char *)&inDummyData,
#ifdef _TARG_68000		
							sizeof(inDummyData)
#endif 
#ifdef __arm
							sizeof(int)
#endif 

							);
	PFR_HANDLE_ERROR(inError);


	inError = shVarAddField(pchPFRRecord,
							PFR_TRAN_OBJ_FILE,
							(unsigned char *) TRAN_OBJ_FILE_NAME,
							strlen(TRAN_OBJ_FILE_NAME) + 1);


	/* Check if an error occured */
	if (!inError)
	{
		inError = inWriteFlexiToFile(POWER_FAIL_FILE_NAME,
								  pchPFRRecord,
								  &offset);
	}//if

#if 0
		inError = shVarUpdateField(pchPFRRecord,
								PFR_STATE,
								(unsigned char *)&inCurrentState,
#ifdef _TARG_68000										
								sizeof (short)
#endif 
#ifdef __arm

								sizeof(int)
#endif 

								);

#endif /* 0 */
	return inError;
}//inInitPowerFailFile






/*****************************************************************************
* @func int | vdSetPFRState |
* Updates the state information within the PFR state file.
* @parm TRANSACTION_OBJECT | tranObject |
*       The current transaction data block.
* @parm short | inCurrentState |
*       State set in the PFR state file
* @parm char | chStoreTranObjFlag |
*       1-byte flag.  If this parameter is 0, the Transaction Object is
*		Not Stored.  If it is set to 1, the Transaction Object is stored.
* @parm void * | pvoAdditionalFlexRec |
*		Buffer containing additional Flexi Record data fields to be stored in the
*		PFR file.  Use this for SoftPay customizations.
* @rdesc return values.
* @flag int    |  Error value. Non-Zero indicates an error has occured.
* @end
*****************************************************************************/
short shSetPFRState(TRANSACTION_OBJECT * tranObject,
				   short inCurrentState,
				   char chStoreTranObjFlag,
				   char chStoreExtendedData,
				   unsigned char * pvoAdditionalFlexRec)
{
	int inFileHandle = -1;
	unsigned char pchNewPFRRecord[MAX_POWER_REC_FLEXI_SIZE];
	char pchDate[9];
	char pchTime[7];
	int inError = 0;
	long lnOffset = 0;
	int inBytesRead = 0;
	char pchDateAndTime[16];
	int inBytesWritten = 0;
	//char chTranObjStored=0;
	//unsigned short inDataLen=0;


	/* Initialise the secondary record */
	vVarInitRecord(pchNewPFRRecord,MAX_POWER_REC_FLEXI_SIZE, 0);

	/* Initialise the date and time to null */
	pchDate[0] = 0;
	pchTime[0] = 0;

	/* Read in the current flexi record from the PFR file */
	inError = inGetFlexiFromFile(POWER_FAIL_FILE_NAME,
					   pchPFRRecord,
					   MAX_POWER_REC_FLEXI_SIZE,
					   &lnOffset);

	/* If the data could NOT be retrieved, then as a default step CREATE A NEW
	* POWER recovery file
	*/
	if (inError)
	{

		/* Initialise the POWER FAIL file and contents */
		inError = inInitPowerFailFile();

		if (!inError)
		{
			/* Try to read in the recod again */
			inError = inGetFlexiFromFile(POWER_FAIL_FILE_NAME,
						   pchPFRRecord,
						   MAX_POWER_REC_FLEXI_SIZE,
						   &lnOffset);
		}//if
	}//if

	if (!inError)
	{
			/* Get the current date and time */
			SVC_CLOCK(GET_CLOCK, (char *)pchDateAndTime, 15);
			memcpy(pchDate,pchDateAndTime,8);
			pchDate[8] = 0;
			memcpy(pchTime,&pchDateAndTime[8],6);
			pchTime[6] = 0;
#if 0
		/* Are we storing the transaction object for this state update */
		inError = shVarUpdateField(pchPFRRecord,
								PFR_TRANOBJ_STORED,
								(unsigned char *)&chStoreTranObjFlag,
#ifdef _TARG_68000										
								sizeof (chStoreTranObjFlag)
#endif 
#if __arm
								sizeof(int)
#endif 
								);
#endif /* 0 */								


		/* Now, Update the fields in the current PFR flexi-record */
		inError = shVarUpdateField(pchPFRRecord,
								PFR_STATE,
								(unsigned char *)&inCurrentState,
#ifdef _TARG_68000										
								sizeof (short)
#endif 
#if __arm
								sizeof(int)
#endif 
                                );

		PFR_HANDLE_ERROR(inError);

		inError = shVarUpdateField(pchPFRRecord,
								PFR_UPDATE_DATE,
								(unsigned char *)pchDate,
#ifdef _TARG_68000												
								PFR_DATE_SIZE);
#endif 								
#if __arm
								12);
#endif 								
		PFR_HANDLE_ERROR(inError);

		inError = shVarUpdateField(pchPFRRecord,
								PFR_UPDATE_TIME,
								(unsigned char *)pchTime,
#ifdef _TARG_68000				
								PFR_TIME_SIZE);
#endif 
#if __arm
								8);
#endif 
		PFR_HANDLE_ERROR(inError);

		/* Are we storing the transaction object for this state update */
		inError = shVarUpdateField(pchPFRRecord,
								PFR_TRANOBJ_STORED,
								(unsigned char *)&chStoreTranObjFlag,
#ifdef _TARG_68000
								sizeof (chStoreTranObjFlag));
#else
                                sizeof (int));
#endif 
		PFR_HANDLE_ERROR(inError);

		/* Add the additional FLEXI rec to the existing record  as a SUB RECORD*/
		shVarAddExternalRecord(pchPFRRecord,
		    					pvoAdditionalFlexRec,
								100);

		/* NOW, Flatten the FLEXI-RECORD */
		inError = shVarFlatten(pchPFRRecord,
							   pchNewPFRRecord);


		/* If all the updates were successful, then write the record to a file */
		if (!inError)
		{

			/* Write the updated record to the PFR file */
			lnOffset = 0;
			inError = inWriteFlexiToFile(POWER_FAIL_FILE_NAME,
										 pchNewPFRRecord,
										 &lnOffset);


			/* Do we store the additional transient data - ONLY IF WE ARE NOT RECOVERING*/
			if ((chStoreExtendedData) && (!PFR_RECOVERING))
			{
				/* Write the additional data to the additional  PFR file */
				lnOffset = 0;
				inError = inWriteFlexiToFile(POWER_ADDITIONAL_PFR_FILE_NAME,
											 pchPFRExtDataFlexiRecord,
											 &lnOffset);

			}//if

			/* Do we need to store the transaction Object */
			if (chStoreTranObjFlag)
			{
				/* Attempt to open the file */
				inFileHandle = open(TRAN_OBJ_FILE_NAME,O_RDWR | O_CREAT);
				if (inFileHandle != -1)
				{
					/* Fill the file with NULLs */
					inBytesWritten
					= write(inFileHandle,(char *)tranObject,sizeof(TRANSACTION_OBJECT));
					close(inFileHandle);
				}//if good file open
			}//if store obTran
		}//if not error on flatten
	}// if (!inError)

	if (!PFR_RECOVERING)
	{
		/* Reset the additional flexi record */
		vVarInitRecord(pchPFRExtDataFlexiRecord, MAX_POWER_REC_FLEXI_SIZE, 0);
	}

	return inError;
}//vdSetPFRState


int PFR_CODE_CHECK(char * a,char *b,short  *  c,char * d,unsigned char * e)
{

	GET_VER_A(a,b,c,d,e);

	return 1;
}

/*****************************************************************************
* @func int | inPFRExecute |
*
* @parm TRANSACTION_OBJECT | tranObject |
*       Executes the function associated with the current state stored in the
*		state file.
* @rdesc return values.
* @flag int    |  Error value. Non-Zero indicates an error has occured.
* @end
*****************************************************************************/
int inPFRExecute()
{

	int inError = 0;
	int inRunError = 0;
	
 //jrd one source
    #ifdef __arm
    unsigned short inDataLen = 0;
    #endif
    #ifdef _TARG_68000
    unsigned int inDataLen = 0;
    #endif
	short pinPFRState[2];
	long lnOffset = 0;
	char chDummy[20];
	TRANSACTION_OBJECT tranObject;
	int inRecoveryCounter = 0;
	int inRecoveryFailureCounter = 0;
	int inFileHandle = 0;
	int inBytesRead = 0;
	char chTranObjStored = 0;
	PFR_TABLE_STRUCT srPfrRecord;
	int inRecord = 0;
	int inFound = 0;
	int result = 0;

	//pdebug (("--inPFRExecute--"));

	/* The run engine runs all functions associated with ID's until a zero is
	found      */
	pinPFRState[1] = 0;

//	LOG_FORMAT_MESSAGE(("HELLO %d %d",pinPFRState[1] ,pinPFRState[1]) );

	/* This global variable is set to indicate a recovery is in progress
	This is needed recovering part of a function */
	PFR_RECOVERING = 1;

	/* This flexi record stores the line number from where a code skip occurs in function.
	In some cases it is necessary to skip over a segment of code when recovering a specific
	function. */
	vVarInitRecord(pchRecoveryLinesFlexi,MAX_LINE_FLEXI_SIZE,0);


	/* Read in the current flexi record from the PFR file */
	inError = inGetFlexiFromFile(POWER_FAIL_FILE_NAME,
					   pchPFRRecord,
					   MAX_POWER_REC_FLEXI_SIZE,
					   &lnOffset);

	/* If an error occurs, then recreate power fail file as DEFAULT.
	*/
	if (inError)
	{

		inError = shSetPFRState(&tranObject,
					 PFR_IDLE_STATE,
					 0,0,
					 (unsigned char*)chDummy);// No subrecord information

		/* Read in the current flexi record from the PFR file */
		lnOffset = 0;

		if (!inError)
		{
			inError = inGetFlexiFromFile(POWER_FAIL_FILE_NAME,
						   pchPFRRecord,
						   MAX_POWER_REC_FLEXI_SIZE,
						   &lnOffset);

		}//if
	}//if

	/* If no error has occured, then run the function associated with the
	the last state recorded */
	if (!inError)
	{
		/* Get the additional power failure information */
		lnOffset = 0;
		inError = inGetFlexiFromFile(POWER_ADDITIONAL_PFR_FILE_NAME,
					   pchPFRExtDataFlexiRecord,
					   MAX_POWER_REC_FLEXI_SIZE,
					   &lnOffset);
		if (inError)
		{

			/* Reset the additional flexi record */
			vVarInitRecord(pchPFRExtDataFlexiRecord, MAX_POWER_REC_FLEXI_SIZE, 0);
		}



		/* Retrieve the last state stored */
		inError = shVarGetField(pchPFRRecord,
							PFR_TRANOBJ_STORED,
							(unsigned char *) &chTranObjStored,
#ifdef _TARG_68000				
							sizeof(char),
#endif 							
#if __arm
							sizeof(int),
#endif 
							&inDataLen);

		/* Do we have to read in the last transaction object stored */
		if (chTranObjStored)
		{

			/* Attempt to open the file */
			inFileHandle = open(TRAN_OBJ_FILE_NAME,O_RDWR);
			if (inFileHandle != -1)
			{
				inBytesRead
				= read(inFileHandle,(char *)&tranObject,sizeof(TRANSACTION_OBJECT));
				close(inFileHandle);
			}
		}

		inError = shVarGetField(pchPFRRecord,
							PFR_STATE,
							(unsigned char *) &pinPFRState[0],
							sizeof(int),
							&inDataLen);
		sprintf(chDummy,(const char*)"PFR STATE:%04x",pinPFRState[0]);
		uinCurrentState = pinPFRState[0];



		/* Load up the associated record from the PFR table */
		inFound = 0;
		for (inRecord = 0;(!inError) && (!inFound);inRecord++)
		{
			inError = inLoadConfRec (POWER_FAIL_STAT_TABLE,
								   sizeof(PFR_TABLE_STRUCT),
								   inRecord,
								   (char *) &srPfrRecord);
			/* Have we found the correct record */

			if (srPfrRecord.inStateIdentifier == pinPFRState[0])
			{
				inFound = 1;
			}
		}//while

		shVarGetField(pchPFRRecord,
								PFR_UPDATE_DATE,
								(unsigned char *)PFR_DATE,//srRcpt.szDate,
								PFR_DATE_SIZE,
								&inDataLen);


		shVarGetField(pchPFRRecord,
								PFR_UPDATE_TIME,
								(unsigned char *)PFR_TIME, //srRcpt.szTime,
								PFR_TIME_SIZE,
								&inDataLen);

		PFR_LAST_STATE = pinPFRState[0];
		//sprintf(srRcpt.szSpecialMessage,"%02X Hex",pinPFRState[0]);


		if ((!inError) && (inFound))
		{
			/* NOW, Run all the functions associated with the selected form */
			inRunError = inRunEngine ((short *)srPfrRecord.inRecoveryFunctions,
									(void *)&tranObject);
            if ((pinPFRState[0] != PFR_IDLE_STATE) && (inRunError != VS_SUCCESS))
            	pstGetSet_pobTran (&tranObject, 2, &result);



			/* Log the recovery attempt counter, and recovery failure counter
			if a failure occured
			*/
			inError = shVarGetField(pchPFRRecord,
									PFR_FAILURE_COUNTER,
									(unsigned char *) &inRecoveryCounter,
									sizeof(int),
									&inDataLen);

			inError = shVarGetField(pchPFRRecord,
									PFR_REC_FAIL_COUNT,
									(unsigned char *) &inRecoveryFailureCounter,
									sizeof(int),
									&inDataLen);

			/* Increment the recovery counter */
			++inRecoveryCounter;

			/* if an error occured running the function, then increment the failure counter
			*/
			if (inRunError)
			{
				++inRecoveryFailureCounter;
			}


			/* Store the updated values */
			inError = shVarUpdateField(pchPFRRecord,
									PFR_FAILURE_COUNTER,
									(unsigned char *) &inRecoveryCounter,
									sizeof(int));

			inError = shVarUpdateField(pchPFRRecord,
									PFR_REC_FAIL_COUNT,
									(unsigned char *) &inRecoveryFailureCounter,
									sizeof(int));


			/* Write the updated record to the PFR file */
			lnOffset = 0;
			inError = inWriteFlexiToFile(POWER_FAIL_FILE_NAME,
										 pchPFRRecord,
										 &lnOffset);



		}//inError


	}//inError

	/* Set the recovery indicator to zero, which indicates recovery is complete */
	PFR_RECOVERING = 0;
	return inError;
}

/*****************************************************************************
* @func int | inPFRIdle |
* The IDLE state recovery fucntion.
* @rdesc return values.
* @flag int    |  Error value. Non-Zero indicates an error has occured.
* @end
*****************************************************************************/
int inPFRIdle(TRANSACTION_OBJECT * tranObject)
{
//	printf("IDLE STATE\n");
	return 0;
}



/*****************************************************************************
* @func int | vPFRSetPartFunc |
* This function stores specific line numbers of code, so that x,starting at these,
* line numbers, segments of code can be skipped.
* @rdesc return values.
* @flag int    |  Error value. Non-Zero indicates an error has occured.
* @end
*****************************************************************************/
int vPFRSetPartFunc(int line)
{
	unsigned char dmmy[5];
	 //jrd one source
    #ifdef __arm
    unsigned short inDataLen = 0;
    #endif
    #ifdef _TARG_68000
    unsigned int inDataLen = 0;
    #endif
	
	int inError =0;
	/* Check if this is being called after a recovery state */
	if (!PFR_RECOVERING)
	{
		/* Store the current host record */
		shVarAddField(pchRecoveryLinesFlexi,line,dmmy,1);
		return 1;
	}
	else
	{
		/* Check if the line passed was stored with the state */
		inError +=shVarGetField(pchRecoveryLinesFlexi,
								line,dmmy,5,&inDataLen);
		if (inError)
		{
			/* Execute the code block */
			return 1;
		}
		else
		{
			/* Dont Execute the code block */
			return 0;
		}
	}
}//vPFRSetPartFunc

static char ifOddBoundary(unsigned char*buff)
{
    return (char)(((long)buff) % 2);
}

/*****************************************************************************
* @func int | inPFRStateStoreAll |
* This function stores ALL transient data and the specified state.
* @rdesc return values.
* @flag int    |  Error value. Non-Zero indicates an error has occured.
* @end
*****************************************************************************/
int inPFRStateStoreAll(int inCurrentState,
						TRANSACTION_OBJECT * pobTran,
						char chStoreTransactionObject,
						char chStoreExtendedData)
{
	int inError = 0;
 //jrd one source
    #ifdef __arm
    short inHostDataSize=0;
    #endif
    #ifdef _TARG_68000
    int inHostDataSize=0;
    #endif
	
	void *tmpCdt;
	unsigned char ucHDTRecBuff[SIZE_HDT_REC+1];
	unsigned char ucMHTRecBuff[SIZE_MHT_REC+1];
	unsigned char ucMITRecBuff[SIZE_MIT_REC+1];
	unsigned char ucBDTRecBuff[SIZE_BDT_REC+1];
	unsigned char *ucHDTRec = ucHDTRecBuff;
	unsigned char *ucMHTRec = ucMHTRecBuff;
	unsigned char *ucMITRec = ucMITRecBuff;
	unsigned char *ucBDTRec = ucBDTRecBuff;


    if(ifOddBoundary(ucHDTRec))   /* if on odd boundary increment pointer */
        ucHDTRec++;
    if(ifOddBoundary(ucMHTRec))   /* if on odd boundary increment pointer */
        ucMHTRec++;
    if(ifOddBoundary(ucMITRec))   /* if on odd boundary increment pointer */
        ucMITRec++;
    if(ifOddBoundary(ucBDTRec))   /* if on odd boundary increment pointer */
        ucBDTRec++;
	if (!PFR_RECOVERING)
	{
		/* Store the current host record */
		vdCopyHDTRecFromStruct( ucHDTRec );
		inAddExternalPfrData(PFR_HOST_DEFINITION_RECORD,ucHDTRec,SIZE_HDT_REC);

		/* Store the current Receipt record */
		inAddExternalPfrData(PFR_GVAR_RECEIPT_RECORD,(unsigned char *)&srRcpt,sizeof(srRcpt));

			/* Store the current MIT record */
		vdCopyMITRecFromStruct( ucMITRec );
		inAddExternalPfrData(PFR_MIT_RECORD,ucMITRec,SIZE_MIT_REC);

			/* Store the current MHT record */
		vdCopyMHTRecFromStruct( ucMHTRec );
		inAddExternalPfrData(PFR_MHT_RECORD,(unsigned char *)ucMHTRec,SIZE_MHT_REC);

        /* Store the current BDT record */
        vdCopyBDTRecFromStruct( ucBDTRec );
		inAddExternalPfrData(PFR_BDT_RECORD,(unsigned char *)ucBDTRec,SIZE_BDT_REC);

		/* Store the current Card record */
		tmpCdt = pvdGetCDTRec();
		inAddExternalPfrData(PFR_CDT_RECORD,(unsigned char *)tmpCdt,SIZE_CDT_REC);



		inError = shGetRecordLength(pobTran->srBRec.pchHostData,&inHostDataSize);

		if (!inError && inHostDataSize != 0)
		{
			/* Store the current Flexi record */
			inAddExternalPfrData(PFR_BATCH_FLEXI_RECORD,
								pobTran->srBRec.pchHostData,
								inHostDataSize);
		}//if


		inError = shGetRecordLength(pobTran->pchFlexiData,&inHostDataSize);

		if (!inError && inHostDataSize != 0)
		{
			/* Store the current Flexi record */
			inAddExternalPfrData(PFR_TRANS_FLEXI_RECORD,
								pobTran->pchFlexiData,
								inHostDataSize);
		}//if

		/* Check if this is being called in a recovery state */
		if (!PFR_RECOVERING)
		{
			inError = shGetRecordLength(pchRecoveryLinesFlexi,&inHostDataSize);

    		if (!inError && inHostDataSize != 0)
    		{
    			/* Store the current recovery lines */
    			inAddExternalPfrData(PFR_LINE_FLEXI,
    								pchRecoveryLinesFlexi,
    								inHostDataSize);

    			vVarInitRecord(pchRecoveryLinesFlexi,MAX_LINE_FLEXI_SIZE,0);
			}
		} /* end if not powerfail recovering */

	}//!PFR_RECOVERING

	/* Set the power failure recovery state to store all the data */
	shSetPFRState(pobTran,
					inCurrentState,
					chStoreTransactionObject, // store the transation object,
					chStoreExtendedData,
				    NULL);// unsigned char * pvoAdditionalFlexRec



	return 0;

}







/*****************************************************************************
* @func int | inPFRStateRestoreAll |
* This function stores ALL transient data and the specified state.
* @rdesc return values.
* @flag int    |  Error value. Non-Zero indicates an error has occured.
* @end
*****************************************************************************/
int inPFRStateRestoreAll(TRANSACTION_OBJECT * pobTran)
{

	
 //jrd one source
    #ifdef __arm
    unsigned short inDataLen = 0;
    #endif
    #ifdef _TARG_68000
    unsigned int  inDataLen = 0;
    #endif	
	int inError = 0;
	void *tmpCdt;
	unsigned char tmpHDT[SIZE_HDT_REC];
	unsigned char tmpMHT[SIZE_MHT_REC];
	unsigned char tmpMIT[SIZE_MIT_REC];
	unsigned char tmpBDT[SIZE_BDT_REC];

	//pdebug (("--inPFRStateRestoreAll--"));

	/* Initialise the batch Flexi record */
	pobTran->srBRec.pchHostData = (unsigned char *)pchAlloc(MAX_HOST_DATA_FLEXI_SZ);
    pobTran->pchFlexiData = (unsigned char *)pchAlloc(MAX_TRAN_FLEXI_REC_SIZE);

	/* Read in all transient global data stored  */
	inError +=shVarGetField(pchPFRExtDataFlexiRecord,
				PFR_HOST_DEFINITION_RECORD,
				tmpHDT,
				SIZE_HDT_REC,
				&inDataLen);
	vdRestoreHDTRecFromStruct( tmpHDT );

	inError +=shVarGetField(pchPFRExtDataFlexiRecord,
				PFR_BDT_RECORD,
				tmpBDT,
				SIZE_BDT_REC,
				&inDataLen);
	vdRestoreBDTRecFromStruct( tmpBDT );

	inError += shVarGetField(pchPFRExtDataFlexiRecord,
				PFR_GVAR_RECEIPT_RECORD,
				(unsigned char *) &srRcpt,
				sizeof(srRcpt),
				&inDataLen);


	tmpCdt = pvdGetCDTRec();
	inError += shVarGetField(pchPFRExtDataFlexiRecord,
				PFR_CDT_RECORD,
				(unsigned char *) tmpCdt,
				SIZE_CDT_REC,
				&inDataLen);


	inError += shVarGetField(pchPFRExtDataFlexiRecord,
				PFR_MIT_RECORD,
				tmpMIT,
				SIZE_MIT_REC,
				&inDataLen);
	vdRestoreMITRecFromStruct( tmpMIT );

	inError += shVarGetField(pchPFRExtDataFlexiRecord,
				PFR_MHT_RECORD,
				tmpMHT,
				SIZE_MHT_REC,
				&inDataLen);
	vdRestoreMHTRecFromStruct(tmpMHT );

	inError += shVarGetField(pchPFRExtDataFlexiRecord,
				PFR_LINE_FLEXI,
				(unsigned char *) pchRecoveryLinesFlexi,
				MAX_LINE_FLEXI_SIZE,
				&inDataLen);


	if (!inError)
	{
		inError =shVarGetField(pchPFRExtDataFlexiRecord,
					PFR_BATCH_FLEXI_RECORD,
					(unsigned char *) pobTran->srBRec.pchHostData,
					MAX_HOST_DATA_FLEXI_SZ, // can set any large size here, because the size of the record will never exceed the buffer size
					&inDataLen);
		if (inError)
		{
			/* Reset the additional flexi record */
			vVarInitRecord((unsigned char *) pobTran->srBRec.pchHostData, MAX_HOST_DATA_FLEXI_SZ, 0);
			// If we are at the beginning of a settlement then the batch rec dynamic
			// host data hasn't been created yet and that is O.K.
            if ((inError == VAR_FIELD_NOT_FOUND || inError == VAR_NULL_POINTER)
                && PFR_LAST_STATE == PFR_BEGIN_SETTLEMENT)
                inError = VS_SUCCESS;
		}


        shVarGetField(pchPFRExtDataFlexiRecord,
    					PFR_TRANS_FLEXI_RECORD,
    					(unsigned char *) pobTran->pchFlexiData,
    					MAX_TRAN_FLEXI_REC_SIZE, // can set any large size here, because the size of the record will never exceed the buffer size
    					&inDataLen);
        vVarInitRecord(pobTran->pchFlexiData, MAX_TRAN_FLEXI_REC_SIZE, 0);

	} /* end if not Error */

	return (inError);

}



/*****************************************************************************
* @func int | inPFRReceiptRecovery |
* The receipt printing recovery function.
* @rdesc return values.
* @flag int    |  Error value. Non-Zero indicates an error has occured.
* @end
*****************************************************************************/
int inPFRReceiptRecoveryPending(TRANSACTION_OBJECT * tranObject)
{
	/* Free space allocated for the batch flexi record */
	vdFree((char *)tranObject->srBRec.pchHostData);


	return 0;
}




/*****************************************************************************
* @func int | inPFRReceiptRecovery |
* The receipt printing recovery function.
* @rdesc return values.
* @flag int    |  Error value. Non-Zero indicates an error has occured.
* @end
*****************************************************************************/
int inPFRReceiptRecovery(TRANSACTION_OBJECT * tranObject)
{


	/* Try to print the receipt with the saved transaction object */
	inFlowPrintReceipt(tranObject);


	/* Free space allocated for the batch flexi record */
	vdFree((char *)tranObject->srBRec.pchHostData);

	return 0;
}



/*****************************************************************************
* @func int | inPFRAccumRecovery |
* The receipt printing recovery function.
* @rdesc return values.
* @flag int    |  Error value. Non-Zero indicates an error has occured.
* @end
*****************************************************************************/
int inPFRAccumRecovery(TRANSACTION_OBJECT * tranObject)
{


	/* Try to print the receipt with the saved transaction object */
	inFlowPrintReceipt(tranObject);


	/* Free space allocated for the batch flexi record */
	vdFree((char *)tranObject->srBRec.pchHostData);

	return 0;
}







/*****************************************************************************
* @func int | inPFRBatchRecovery |
* The receipt printing recovery function.
* @rdesc return values.
* @flag int    |  Error value. Non-Zero indicates an error has occured.
* @end
*****************************************************************************/
int inPFRBatchRecovery(TRANSACTION_OBJECT * tranObject)
{


	#ifdef BATCH_DEFINED
	/* Open the batch */
	inOpenDCBatch(tranObject);

	/* Update the batch with the stored information */
	inUpdateBatchFlow (tranObject);
	#endif


	/* Try to print the receipt with the saved transaction object */
	inFlowPrintReceipt(tranObject);


	/* Free space allocated for the batch flexi record */
	vdFree((char *)tranObject->srBRec.pchHostData);

	return 0;
}


/*****************************************************************************
* @func int | inPFRRecoveryCleanup |
* The free up resources used for the recovery process.
* @rdesc return values.
* @flag int    |  Error value. Non-Zero indicates an error has occured.
* @end
*****************************************************************************/
int inPFRRecoveryCleanup(TRANSACTION_OBJECT * tranObject)
{
	int result = 0;

	//pdebug (("inPFRRecoveryCleanup"));

	/* Free space allocated for the batch flexi record */
	vdFree((char *)tranObject->srBRec.pchHostData);
	/* Set the transaction object back to NULL */
	pstGetSet_pobTran (tranObject,2, &result);

	return 0;
}


/*****************************************************************************
* @func int | inPrintRecoveryMessage |
* Prints a message to indicate power fail recovery is occuring.
* @rdesc return values.
* @flag int    |  Error value. Non-Zero indicates an error has occured.
* @end
*****************************************************************************/
int inPrintRecoveryMessage(TRANSACTION_OBJECT * tranObject)
{
    char szTemplateFileName[FILENAME_SIZE+1];

    if (inGetPrinterType() == NOPRINTER || !fGetEnablePrinter())
    {
        return(VS_SUCCESS);
    }

	strcpy(szTemplateFileName, (const char*)STATIC_DATA_PATH);
    strcat(szTemplateFileName,(const char*)"PFR.FRM");
	inSwitchTemplate (szTemplateFileName);

	/* Set up the printer global variables */
	memcpy(srRcpt.szDate,PFR_DATE,PFR_DATE_SIZE);
	srRcpt.szDate[PFR_DATE_SIZE] = 0;
	memcpy(srRcpt.szTime,PFR_TIME,PFR_TIME_SIZE);
	srRcpt.szTime[PFR_TIME_SIZE] = 0;
	sprintf(srRcpt.szSpecialMessage,(const char*)"%02X Hex",PFR_LAST_STATE);

	
	//if (inPrintLines(&obPrinter,1,7, 0, 0L) != VS_SUCCESS)
	//   return(VS_ERR);

	while(inPrintLines(&obPrinter,1,7, 0, 0L) != VS_SUCCESS);

	//if (inPrintLines(&obPrinter,uinCurrentState + 20,uinCurrentState + 20, 0, 0L) != VS_SUCCESS)
	//    return(VS_ERR);

	while(inPrintLines(&obPrinter,uinCurrentState + 20,uinCurrentState + 20, 0, 0L) != VS_SUCCESS);

	//if(inPrintLines(&obPrinter,8,9, 0, 0L) != VS_SUCCESS)
	//    return(VS_ERR);

	while(inPrintLines(&obPrinter,8,9, 0, 0L) != VS_SUCCESS);

	// Restore default template
    inSelectTemplateFile(&obPrinter);
    inGetDefaultTemplateName(szTemplateFileName);
	inSwitchTemplate (szTemplateFileName);

	return(VS_SUCCESS);
}


/*****************************************************************************
* @func int | inInitSettleRecovery |
* Set up the UI for settlment recovery.
* @rdesc return values.
* @flag int    |  Error value. Non-Zero indicates an error has occured.
* @end
*****************************************************************************/
int inInitSettleRecovery(TRANSACTION_OBJECT * tranObject)
{
	int result = 0;

    //pdebug (("--inInitSettleRecovery--"));

	clrscr();
	vdSetActionFont();
	/* Because we have just recovered, the batch is set as OPEN in trans object */
	tranObject->fBatchOpen = VS_FALSE;

	/* The transaction object has not yet been set in operate.c */
	pstGetSet_pobTran (tranObject,1, &result);

	return 0;
}


/*****************************************************************************
* @func int | inAddPFRFunctions |
* Add all power recovery functions to the RUN ENGINE FLEXI-RECORD,here.
* @rdesc return values.
* @flag int    |  Error value. Non-Zero indicates an error has occured.
* @end
*****************************************************************************/
int inAddPFRFunctions()
{
	int inError = 0;

	/******************************************************/
	/* ADD ALL YOUR POWER FAILURE RECOVERY FUNCTIONS HERE */
	/******************************************************/
	inError = inAddFunctionPointer(PFR_IDLE_STATE_RECOVER, inPFRIdle);
	#ifdef BATCH_DEFINED
	inError += inAddFunctionPointer(PFR_SETTLE_REPORT_RECOVER, inSettleAHost);
	#endif
	inError += inAddFunctionPointer(PFR_DATA_STATE_RECOVER, inPFRStateRestoreAll);
	inError += inAddFunctionPointer(PFR_RECOVERY_CLEANUP,inPFRRecoveryCleanup);
	inError += inAddFunctionPointer(PFR_RECOVERY_MESSAGE,inPrintRecoveryMessage);
	inError += inAddFunctionPointer(PFR_INIT_SETTLE_RECOVERY,inInitSettleRecovery);
	inError += inAddFunctionPointer(PFR_RECOVER_INIT,inInitSettleRecovery);
	return inError;
}//inAddPFRFunctions


/*****************************************************************************
* @func int | inReadPFRFileData |
* Add all power recovery functions to the RUN ENGINE FLEXI-RECORD,here.
* @rdesc return values.
* @flag int    |  Error value. Non-Zero indicates an error has occured.
* @end
*****************************************************************************/
int inReadPFRFiledata(short * pinPFRState,
					  char * pchUpdateDate,
					  char * pchUpdateTime,
					  int * pinFailureCounter,
					  int * pinRecoveryFuncFailCount,
					  unsigned char ** pucFlexiRecBuffer)
{
	int inError = 0;
	long lnOffset = 0;
 //jrd one source
    #ifdef __arm
    unsigned short inDataLen = 0;
    #endif
    #ifdef _TARG_68000
    unsigned int inDataLen = 0;
    #endif
	

	/* Read in the current flexi record from the PFR file */
	inError = inGetFlexiFromFile(POWER_FAIL_FILE_NAME,
					   pchPFRRecord,
					   MAX_POWER_REC_FLEXI_SIZE,
					   &lnOffset);
	if (!inError)
	{
		*pucFlexiRecBuffer = pchPFRRecord;
		inError = shVarGetField(pchPFRRecord,
								PFR_FAILURE_COUNTER,
								(unsigned char *) pinFailureCounter,
								sizeof(int),
								&inDataLen);

		inError = shVarGetField(pchPFRRecord,
								PFR_REC_FAIL_COUNT,
								(unsigned char *) pinRecoveryFuncFailCount,
								sizeof(int),
								&inDataLen);

		/* Do we need to retrieve the transaction Object stored */
		inError = shVarGetField(pchPFRRecord,
								PFR_STATE,
								(unsigned char *) pinPFRState,
								sizeof(int),
								&inDataLen);

		inError = shVarGetField(pchPFRRecord,
								PFR_STATE,
								(unsigned char *) pinPFRState,
								sizeof(int),
								&inDataLen);

		inError = shVarGetField(pchPFRRecord,
									PFR_UPDATE_DATE,
									(unsigned char *)pchUpdateDate,
									PFR_DATE_SIZE,
									&inDataLen);

		inError = shVarGetField(pchPFRRecord,
									PFR_UPDATE_TIME,
									(unsigned char *)pchUpdateTime,
									PFR_TIME_SIZE,
									&inDataLen);
	}//if

	return inError;
}//inReadPFRFiledata

#if 0 // KV1 2001-6-20

/*****************************************************************************
* @func void | vLogComm|
* Writes a log message to COMM1
* @rdesc return values.
* @flag void   |  No return value.
* @end
*****************************************************************************/
void vLogCommS(char * message);

void vLogCommS(char * message)
{
	int xcom;
	struct Opn_Blk xcomblock;

	xcom = open("/dev/COM1", 0);	xcomblock.rate = Rt_9600;
	xcomblock.format = Fmt_A8N1;
	xcomblock.protocol = P_char_mode;

	set_opn_blk(xcom,(char*)(& xcomblock));

	write(xcom,message,strlen(message));
	SVC_WAIT(80);
	close(xcom);

}
#endif // KV1 2001-6-20







